package utils;

/**
 * Kruzni buffer koji skladisti procitane poruke iz stream-a.
 * 
 * @author UrosKrkic & Radivoje Popovic
 */
public class ConnectionBuffer {

	/**
	 * Velicina buffer-a.
	 */
	private int size = 0;

	
	/**
	 * Tip podataka koje buffer skladisti.
	 */
	private String[] data;

	
	/**
	 * Naredna lokacija za citanje.
	 */
	private int nextReadPosition;

	
	/**
	 * Naredna lokacija za pisanje.
	 */
	private int nextWritePosition;

	
	/**
	 * Konstruktor.
	 * @author UrosKrkic & Radivoje Popovic
	 */
	public ConnectionBuffer(int size) {
		this.size = size;
		data = new String[size];
		nextReadPosition = 0;
		nextWritePosition = 0;
	}
	
	

	/**
	 * Metod upisuje novu vrednost u buffer.
	 * @param value - vrednost koja se upisuje u buffer
	 * @author UrosKrkic & Radivoje Popovic
	 */
	public synchronized void write(String value) {
		if ( isFull() ) {
			try {
				wait();
			}
			catch (InterruptedException ie) {
				ie.printStackTrace();
			}
		}
		
		data[nextWritePosition] = value;
		
		nextWritePosition++;
		
		if ( nextWritePosition == size ) {
			nextWritePosition = 0;
		}
		
		notify();
	}



	/**
	 * Metod cita narednu vrednost iz buffer-a.
	 * @return - procitana vrednost iz buffer-a
	 * @author UrosKrkic & Radivoje Popovic
	 */
	public synchronized String read() {
		if ( isEmpty() ) {
			try {
				wait();
			}
			catch (InterruptedException ie) {
				ie.printStackTrace();
			}
		}
		
		String value = data[nextReadPosition];
		
		nextReadPosition++;
		
		if ( nextReadPosition == size ) {
			nextReadPosition = 0;
		}
		
		notify();
		
		return value;
	}


	
	/**
	 * Metod proverava da li je buffer prazan.
	 * @return true, ako je prazan, inace false
	 * @author UrosKrkic & Radivoje Popovic
	 */
	public synchronized boolean isEmpty() {
		return nextReadPosition == nextWritePosition;
	}


	
	/**
	 * Metod proverava da li je buffer pun.
	 * @return true, ako je pun, inace false
	 * @author UrosKrkic & Radivoje Popovic
	 */
	public synchronized boolean isFull() {
		return nextReadPosition == (nextWritePosition + 1) % size;
	}

}
